home *** CD-ROM | disk | FTP | other *** search
/ The World of Computer Software / The World of Computer Software.iso / faq-s.zip / PIBASYN3.MOD < prev    next >
Text File  |  1991-04-16  |  53KB  |  1,026 lines

  1. (*----------------------------------------------------------------------*)
  2. (* Async_Find_Delay  --- Finds delay loop value for 1 millesecond delay *)
  3. (*----------------------------------------------------------------------*)
  4.  
  5. PROCEDURE Async_Find_Delay( VAR One_MS_Delay : INTEGER );
  6.  
  7. (*----------------------------------------------------------------------*)
  8. (*                                                                      *)
  9. (*      Procedure: Async_Find_Delay                                     *)
  10. (*                                                                      *)
  11. (*      Purpose:   Finds loop count value to effect 1 ms delay          *)
  12. (*                                                                      *)
  13. (*      Calling Sequence:                                               *)
  14. (*                                                                      *)
  15. (*         Async_Find_Delay( VAR One_MS_Delay : INTEGER );              *)
  16. (*                                                                      *)
  17. (*            One_MS_Delay --- Resulting loop count for 1 ms delay      *)
  18. (*                                                                      *)
  19. (*      Using result:                                                   *)
  20. (*                                                                      *)
  21. (*            Use loop of form:                                         *)
  22. (*                                                                      *)
  23. (*                      MOV    CX,[>One_MS_Delay]                       *)
  24. (*               Delay: LOOP   Delay                                    *)
  25. (*                                                                      *)
  26. (*            to delay for 1 ms.                                        *)
  27. (*                                                                      *)
  28. (*      Remarks:                                                        *)
  29. (*                                                                      *)
  30. (*         This routine watches over the CPU elapsed timer value for    *)
  31. (*         just one timer interval (55 milleseconds).  During that time *)
  32. (*         we run a tight loop and accumulate the ticks.  The result    *)
  33. (*         is the number of ticks required for a 55 ms delay.  The      *)
  34. (*         ticks for a 1 ms delay = ( ticks for 55 ms ) / 55.           *)
  35. (*                                                                      *)
  36. (*         To avoid overflow problems on fast machines, and to ease the *)
  37. (*         worry about storing results at the second timer tick, we     *)
  38. (*         break up the single long tight loop into a series of short   *)
  39. (*         loops inside an outer loop.  We check if the timer has       *)
  40. (*         expired at the end of each inner short loop.  Then the       *)
  41. (*         time for the 55 ms delay is:                                 *)
  42. (*                                                                      *)
  43. (*            Ticks_for_55 := Inner_Ticks * Outer_Ticks;                *)
  44. (*                                                                      *)
  45. (*         and the corresponding 1 ms delay is:                         *)
  46. (*                                                                      *)
  47. (*            Ticks_For_1  := Ticks_For_55 DIV 55;                      *)
  48. (*                                                                      *)
  49. (*         To simplify things, we choose the inner tick value to be     *)
  50. (*         2 x 55 = 110.  Then:                                         *)
  51. (*                                                                      *)
  52. (*            Ticks_For_1  := ( 110 * Outer_Ticks ) / 55;  ==>          *)
  53. (*            Ticks_For_1  := 2 * Outer_Ticks;                          *)
  54. (*                                                                      *)
  55. (*         The CPU timer is located in four bytes at $0000:$46C.        *)
  56. (*         Interrupt $1A also returns these bytes, but using the        *)
  57. (*         interrupt results in an inaccurate loop count value.         *)
  58. (*                                                                      *)
  59. (*         Thanks to Brian Foley and Kim Kokonnen for help with this    *)
  60. (*         problem.                                                     *)
  61. (*                                                                      *)
  62. (*----------------------------------------------------------------------*)
  63.  
  64. (* STRUCTURED *) CONST
  65.    Hi_Timer         : INTEGER = 0  (* Saves high portion of timer        *);
  66.    Lo_Timer         : INTEGER = 0  (* Saves low portion of timer         *);
  67.    OutCount         : INTEGER = 0  (* Accumulates outer loop counts      *);
  68.  
  69. BEGIN (* Async_Find_Delay *)
  70.  
  71. INLINE(
  72.                              {;}
  73.   $31/$C0/                   {          XOR    AX,AX                 ;Clear AX to zero}
  74.   $8E/$C0/                   {          MOV    ES,AX                 ;Allow low-memory access}
  75.                              {;}
  76.   $C7/$06/>OUTCOUNT/$00/$00/ {          MOV    WORD [>OutCount],0    ;Clear outer loop counter}
  77.                              {;}
  78.   $FA/                       {          CLI                          ;No interrupts while reading}
  79.   $26/$8B/$0E/>$46E/         {      ES: MOV    CX,[>$46E]            ;Hi part of CPU timer value}
  80.   $26/$8B/$16/>$46C/         {      ES: MOV    DX,[>$46C]            ;Lo part of CPU timer value}
  81.   $FB/                       {          STI                          ;Interrupts back on}
  82.                              {;}
  83.   $89/$0E/>HI_TIMER/         {          MOV    [>Hi_Timer],CX        ;Save hi part of timer}
  84.   $89/$16/>LO_TIMER/         {          MOV    [>Lo_Timer],DX        ;Save low part of timer}
  85.                              {;}
  86.   $FA/                       {Loop1:    CLI                          ;No interrupts while reading}
  87.                              {;}
  88.   $26/$8B/$0E/>$46E/         {      ES: MOV    CX,[>$46E]            ;Hi part of CPU timer value}
  89.   $26/$8B/$16/>$46C/         {      ES: MOV    DX,[>$46C]            ;Lo part of CPU timer value}
  90.                              {;}
  91.   $FB/                       {          STI                          ;Interrupts back on}
  92.                              {;}
  93.   $89/$C8/                   {          MOV    AX,CX                 ;Save CX and DX for later}
  94.   $89/$D3/                   {          MOV    BX,DX}
  95.                              {;}
  96.   $2B/$06/>HI_TIMER/         {          SUB    AX,[>Hi_Timer]        ;Subtract low order part}
  97.   $1B/$1E/>LO_TIMER/         {          SBB    BX,[>Lo_Timer]        ;Subtract high order part}
  98.                              {;}
  99.   $74/$E6/                   {          JE     Loop1                 ;Continue until non-0 tick difference}
  100.                              {;}
  101.   $89/$0E/>HI_TIMER/         {          MOV    [>Hi_Timer],CX        ;Save hi part}
  102.   $89/$16/>LO_TIMER/         {          MOV    [>Lo_Timer],DX        ;Save low part}
  103.                              {;}
  104.   $B9/$6E/$00/               {Loop2:    MOV    CX,110                ;Run short delay loop.}
  105.   $E2/$FE/                   {Delay:    LOOP   Delay}
  106.                              {;}
  107.   $FA/                       {          CLI                          ;No interrupts while reading}
  108.                              {;}
  109.   $26/$8B/$0E/>$46E/         {      ES: MOV    CX,[>$46E]            ;Hi part of CPU timer value}
  110.   $26/$8B/$16/>$46C/         {      ES: MOV    DX,[>$46C]            ;Lo part of CPU timer value}
  111.                              {;}
  112.   $FB/                       {          STI                          ;Interrupts back on}
  113.                              {;}
  114.   $FF/$06/>OUTCOUNT/         {          INC    WORD [>OutCount]      ;Increment outer loop count}
  115.                              {;}
  116.   $2B/$0E/>HI_TIMER/         {          SUB    CX,[>Hi_Timer]        ;Subtract low order part}
  117.   $1B/$16/>LO_TIMER/         {          SBB    DX,[>Lo_Timer]        ;Subtract high order part}
  118.                              {;}
  119.   $74/$E1/                   {          JE     Loop2                 ;Keep going if next tick not found}
  120.                              {;}
  121.   $A1/>OUTCOUNT/             {          MOV    AX,[>OutCount]        ;Pick up outer loop counter}
  122.   $D1/$E0/                   {          SHL    AX,1                  ;* 2 = ticks for 1 ms delay}
  123.                              {;}
  124.   $C4/$BE/>ONE_MS_DELAY/     {          LES    DI,[BP+>One_MS_Delay] ;Get address of result}
  125.   $26/$89/$05);              {      ES: MOV    [DI],AX               ;Store result}
  126.  
  127. END   (* Async_Find_Delay *);
  128.  
  129. (*----------------------------------------------------------------------*)
  130. (*               Async_Init --- Initialize Asynchronous Variables       *)
  131. (*----------------------------------------------------------------------*)
  132.  
  133. PROCEDURE Async_Init( Async_Buffer_Max  : INTEGER;
  134.                       Async_OBuffer_Max : INTEGER;
  135.                       Async_High_Lev1   : INTEGER;
  136.                       Async_High_Lev2   : INTEGER;
  137.                       Async_Low_Lev     : INTEGER );
  138.  
  139. (*----------------------------------------------------------------------*)
  140. (*                                                                      *)
  141. (*     Procedure:  Async_Init                                           *)
  142. (*                                                                      *)
  143. (*     Purpose:    Initializes variables                                *)
  144. (*                                                                      *)
  145. (*     Calling Sequence:                                                *)
  146. (*                                                                      *)
  147. (*         Async_Init( Async_Buffer_Max  : INTEGER;                     *)
  148. (*                     Async_OBuffer_Max : INTEGER;                     *)
  149. (*                     Async_High_Lev1   : INTEGER;                     *)
  150. (*                     Async_High_Lev2   : INTEGER;                     *)
  151. (*                     Async_Low_Lev     : INTEGER );                   *)
  152. (*                                                                      *)
  153. (*     Calls:  Async_Find_Delay                                         *)
  154. (*             TurnOffTimeSharing                                       *)
  155. (*             TurnOnTimeSharing                                        *)
  156. (*                                                                      *)
  157. (*----------------------------------------------------------------------*)
  158.  
  159. VAR
  160.    I: INTEGER;
  161.  
  162. (*----------------------------------------------------------------------*)
  163.  
  164. BEGIN   (* Async_Init *)
  165.                                    (* No port open yet.                 *)
  166.    Async_Open_Flag        := FALSE;
  167.  
  168.                                    (* No XON/XOFF handling yet.         *)
  169.    Async_XOFF_Sent        := FALSE;
  170.    Async_XOFF_Received    := FALSE;
  171.    Async_XOFF_Rec_Display := FALSE;
  172.    Async_XON_Rec_Display  := FALSE;
  173.    Async_Send_XOFF        := FALSE;
  174.  
  175.                                    (* Sender not enabled.               *)
  176.    Async_Sender_On        := FALSE;
  177.  
  178.                                    (* Set up empty receive buffer       *)
  179.    Async_Buffer_Overflow  := FALSE;
  180.    Async_Buffer_Used      := 0;
  181.    Async_MaxBufferUsed    := 0;
  182.    Async_Buffer_Head      := 0;
  183.    Async_Buffer_Tail      := 0;
  184.                                    (* Set up empty send buffer.         *)
  185.    Async_OBuffer_Overflow := FALSE;
  186.    Async_OBuffer_Used     := 0;
  187.    Async_MaxOBufferUsed   := 0;
  188.    Async_OBuffer_Head     := 0;
  189.    Async_OBuffer_Tail     := 0;
  190.                                    (* Set default wait time for output   *)
  191.                                    (* buffer to drain when it fills up.  *)
  192.    Async_Output_Delay     := 500;
  193.  
  194.                                    (* No modem or line errors yet.       *)
  195.    Async_Line_Status      := 0;
  196.    Async_Modem_Status     := 0;
  197.    Async_Line_Error_Flags := 0;
  198.                                    (* No noise rejection by default      *)
  199.  
  200.    Async_Reject_Noise     := FALSE;
  201.    Async_Noise_Char       := CHR( 0 );
  202.  
  203.                                    (* Get buffer sizes *)
  204.  
  205.    IF ( Async_Buffer_Max > 0 ) THEN
  206.       Async_Buffer_Size := Async_Buffer_Max  - 1
  207.    ELSE
  208.       Async_Buffer_Size := 4095;
  209.  
  210.    IF ( Async_OBuffer_Max > 0 ) THEN
  211.       Async_OBuffer_Size := Async_OBuffer_Max - 1
  212.    ELSE
  213.       Async_OBuffer_Size := 1131;
  214.  
  215.                                    (* Get receive buffer overflow *)
  216.                                    (* check-points.               *)
  217.    IF ( Async_Low_Lev > 0 ) THEN
  218.       Async_Buffer_Low := Async_Low_Lev
  219.    ELSE
  220.       Async_Buffer_Low := Async_Buffer_Size DIV 4;
  221.  
  222.    IF ( Async_High_Lev1 > 0 ) THEN
  223.       Async_Buffer_High := Async_High_Lev1
  224.    ELSE
  225.       Async_Buffer_High := ( Async_Buffer_Size DIV 4 ) * 3;
  226.  
  227.    IF ( Async_High_Lev2 > 0 ) THEN
  228.       Async_Buffer_High_2 := Async_High_Lev2
  229.    ELSE
  230.       Async_Buffer_High_2 := ( Async_Buffer_Size DIV 10 ) * 9;
  231.  
  232.                                    (* Allocate buffers *)
  233.  
  234.    GETMEM( Async_Buffer_Ptr  , Async_Buffer_Size  + 1 );
  235.    GETMEM( Async_OBuffer_Ptr , Async_OBuffer_Size + 1 );
  236.  
  237.                                    (* No UART addresses defined yet *)
  238.    Async_Uart_IER         := 0;
  239.    Async_Uart_IIR         := 0;
  240.    Async_Uart_MSR         := 0;
  241.    Async_Uart_LSR         := 0;
  242.    Async_Uart_MCR         := 0;
  243.                                    (* Set default port addresses *)
  244.                                    (* and default IRQ lines      *)
  245.    FOR I := 1 TO MaxComPorts DO
  246.       BEGIN
  247.          Com_Base[I]  := Default_Com_Base [I];
  248.          Com_Irq [I]  := Default_Com_Irq  [I];
  249.          Com_Int [I]  := Default_Com_Int  [I];
  250.       END;
  251.                                    (* Get the delay loop value for 1 ms *)
  252.                                    (* delay loops.                      *)
  253.  
  254. (* ---- You should turn off time sharing if running under a multitasker *)
  255. (* ---- to get an accurate delay loop value.  If MTASK is $DEFINEd,     *)
  256. (* ---- then the calls to the PibMDos routines for interfacing with     *)
  257. (* ---- multitaskers will be generated.                                 *)
  258.  
  259. {$IFDEF MTASK}
  260.    IF TimeSharingActive THEN
  261.       TurnOffTimeSharing;
  262. {$ENDIF}
  263.  
  264.    Async_Find_Delay( Async_OneMSDelay );
  265.  
  266. {$IFDEF MTASK}
  267.    IF TimeSharingActive THEN
  268.       TurnOnTimeSharing;
  269. {$ENDIF}
  270.  
  271. END     (* Async_Init *);
  272.  
  273. (*----------------------------------------------------------------------*)
  274. (*      Async_Carrier_Detect --- Check for modem carrier detect         *)
  275. (*----------------------------------------------------------------------*)
  276.  
  277. FUNCTION Async_Carrier_Detect : BOOLEAN;
  278.  
  279. (*----------------------------------------------------------------------*)
  280. (*                                                                      *)
  281. (*     Function:   Async_Carrier_Detect                                 *)
  282. (*                                                                      *)
  283. (*     Purpose:    Looks for modem carrier detect                       *)
  284. (*                                                                      *)
  285. (*     Calling Sequence:                                                *)
  286. (*                                                                      *)
  287. (*        Flag := Async_Carrier_Detect : BOOLEAN;                       *)
  288. (*                                                                      *)
  289. (*           Flag is set TRUE if carrier detected, else FALSE.          *)
  290. (*                                                                      *)
  291. (*     Calls:  None                                                     *)
  292. (*                                                                      *)
  293. (*----------------------------------------------------------------------*)
  294.  
  295. BEGIN (* Async_Carrier_Detect *)
  296.  
  297.    Async_Carrier_Detect := ODD( PORT[ Async_Uart_MSR ] SHR 7 ) OR
  298.                            Async_Hard_Wired_On;
  299.  
  300. END   (* Async_Carrier_Detect *);
  301.  
  302. (*----------------------------------------------------------------------*)
  303. (*      Async_Carrier_Drop --- Check for modem carrier drop/timeout     *)
  304. (*----------------------------------------------------------------------*)
  305.  
  306. FUNCTION Async_Carrier_Drop : BOOLEAN;
  307.  
  308. (*----------------------------------------------------------------------*)
  309. (*                                                                      *)
  310. (*     Function:   Async_Carrier_Drop                                   *)
  311. (*                                                                      *)
  312. (*     Purpose:    Looks for modem carrier drop/timeout                 *)
  313. (*                                                                      *)
  314. (*     Calling Sequence:                                                *)
  315. (*                                                                      *)
  316. (*        Flag := Async_Carrier_Drop : BOOLEAN;                         *)
  317. (*                                                                      *)
  318. (*           Flag is set TRUE if carrier dropped, else FALSE.           *)
  319. (*                                                                      *)
  320. (*     Calls:  None                                                     *)
  321. (*                                                                      *)
  322. (*----------------------------------------------------------------------*)
  323.  
  324. BEGIN (* Async_Carrier_Drop *)
  325.  
  326.    Async_Carrier_Drop := NOT ( ODD( PORT[ Async_Uart_MSR ] SHR 7 ) OR
  327.                                Async_Hard_Wired_On );
  328.  
  329. END   (* Async_Carrier_Drop *);
  330.  
  331. (*----------------------------------------------------------------------*)
  332. (*      Async_Term_Ready --- Set terminal ready status                  *)
  333. (*----------------------------------------------------------------------*)
  334.  
  335. PROCEDURE Async_Term_Ready( Ready_Status : BOOLEAN );
  336.  
  337. (*----------------------------------------------------------------------*)
  338. (*                                                                      *)
  339. (*     Procedure:  Async_Term_Ready                                     *)
  340. (*                                                                      *)
  341. (*     Purpose:    Sets terminal ready status                           *)
  342. (*                                                                      *)
  343. (*     Calling Sequence:                                                *)
  344. (*                                                                      *)
  345. (*        Async_Term_Ready( Ready_Status : BOOLEAN );                   *)
  346. (*                                                                      *)
  347. (*           Ready_Status --- Set TRUE to set terminal ready on,        *)
  348. (*                            Set FALSE to set terminal ready off.      *)
  349. (*                                                                      *)
  350. (*     Calls:  None                                                     *)
  351. (*                                                                      *)
  352. (*----------------------------------------------------------------------*)
  353.  
  354. VAR
  355.    Mcr_Value: BYTE;
  356.  
  357. BEGIN (* Async_Term_Ready *)
  358.  
  359.    Mcr_Value := PORT[ Async_Uart_MCR ];
  360.  
  361.    IF ODD( Mcr_Value ) THEN
  362.       Mcr_Value := Mcr_Value - 1;
  363.  
  364.    IF Ready_Status THEN
  365.       Mcr_Value := Mcr_Value + 1;
  366.  
  367.    PORT[ Async_Uart_MCR ] := Mcr_Value;
  368.  
  369.    Async_Clear_Errors;
  370.  
  371. END   (* Async_Term_Ready *);
  372.  
  373. (*----------------------------------------------------------------------*)
  374. (*          Async_Buffer_Check --- Check if character in buffer         *)
  375. (*----------------------------------------------------------------------*)
  376.  
  377. FUNCTION Async_Buffer_Check : BOOLEAN;
  378.  
  379. (*----------------------------------------------------------------------*)
  380. (*                                                                      *)
  381. (*     Function:   Async_Buffer_Check                                   *)
  382. (*                                                                      *)
  383. (*     Purpose:    Check if character in buffer                         *)
  384. (*                                                                      *)
  385. (*     Calling Sequence:                                                *)
  386. (*                                                                      *)
  387. (*        Flag := Async_Buffer_Check : BOOLEAN;                         *)
  388. (*                                                                      *)
  389. (*           Flag returned TRUE if character received in buffer,        *)
  390. (*           Flag returned FALSE if no character received.              *)
  391. (*                                                                      *)
  392. (*     Calls:  None                                                     *)
  393. (*                                                                      *)
  394. (*     Remarks:                                                         *)
  395. (*                                                                      *)
  396. (*       This routine only checks if a character has been received      *)
  397. (*       and thus can be read; it does NOT return the character.        *)
  398. (*       Use Async_Receive to read the character.                       *)
  399. (*                                                                      *)
  400. (*----------------------------------------------------------------------*)
  401.  
  402. BEGIN   (* Async_Buffer_Check *)
  403.  
  404.    Async_Buffer_Check := ( Async_Buffer_Head <> Async_Buffer_Tail );
  405.  
  406. END     (* Async_Buffer_Check *);
  407.  
  408. (*----------------------------------------------------------------------*)
  409. (*          Async_Line_Error --- Check if line status error occurred    *)
  410. (*----------------------------------------------------------------------*)
  411.  
  412. FUNCTION Async_Line_Error( VAR Error_Flags: BYTE ) : BOOLEAN;
  413.  
  414. (*----------------------------------------------------------------------*)
  415. (*                                                                      *)
  416. (*     Function:   Async_Line_Error                                     *)
  417. (*                                                                      *)
  418. (*     Purpose:    Check if line status error occurred                  *)
  419. (*                                                                      *)
  420. (*     Calling Sequence:                                                *)
  421. (*                                                                      *)
  422. (*        Flag := Async_Line_Error(VAR Error_Flags: BYTE): BOOLEAN;     *)
  423. (*                                                                      *)
  424. (*           Error_Flags --- Current error flags                        *)
  425. (*                                                                      *)
  426. (*           Flag returned TRUE if line status error occurred,          *)
  427. (*           Flag returned FALSE if no error.                           *)
  428. (*                                                                      *)
  429. (*     Calls:  None                                                     *)
  430. (*                                                                      *)
  431. (*     Remarks:                                                         *)
  432. (*                                                                      *)
  433. (*        The line status error flag is cleared here.                   *)
  434. (*                                                                      *)
  435. (*----------------------------------------------------------------------*)
  436.  
  437. BEGIN   (* Async_Line_Error *)
  438.  
  439.    Async_Line_Error       := ( Async_Line_Error_Flags <> 0 );
  440.    Error_Flags            := Async_Line_Error_Flags;
  441.    Async_Line_Error_Flags := 0;
  442.  
  443. END     (* Async_Line_Error  *);
  444.  
  445. (*----------------------------------------------------------------------*)
  446. (*            Async_Ring_Detect --- Check for phone ringing             *)
  447. (*----------------------------------------------------------------------*)
  448.  
  449. FUNCTION Async_Ring_Detect : BOOLEAN;
  450.  
  451. (*----------------------------------------------------------------------*)
  452. (*                                                                      *)
  453. (*     Function:   Async_Ring_Detect                                    *)
  454. (*                                                                      *)
  455. (*     Purpose:    Looks for phone ringing                              *)
  456. (*                                                                      *)
  457. (*     Calling Sequence:                                                *)
  458. (*                                                                      *)
  459. (*        Flag := Async_Ring_Detect : BOOLEAN;                          *)
  460. (*                                                                      *)
  461. (*           Flag is set TRUE if ringing detected, else FALSE.          *)
  462. (*                                                                      *)
  463. (*     Calls:  None                                                     *)
  464. (*                                                                      *)
  465. (*----------------------------------------------------------------------*)
  466.  
  467. BEGIN (* Async_Ring_Detect *)
  468.  
  469.    Async_Ring_Detect := ODD( PORT[ Async_Uart_MSR ] SHR 6 );
  470.  
  471. END   (* Async_Ring_Detect *);
  472.  
  473. (*----------------------------------------------------------------------*)
  474. (*          Async_Send_Break --- Send break (attention) signal          *)
  475. (*----------------------------------------------------------------------*)
  476.  
  477. PROCEDURE Async_Send_Break;
  478.  
  479. (*----------------------------------------------------------------------*)
  480. (*                                                                      *)
  481. (*     Procedure:  Async_Send_Break                                     *)
  482. (*                                                                      *)
  483. (*     Purpose:    Sends break signal over communications port          *)
  484. (*                                                                      *)
  485. (*     Calling Sequence:                                                *)
  486. (*                                                                      *)
  487. (*        Async_Send_Break;                                             *)
  488. (*                                                                      *)
  489. (*     Calls:  None                                                     *)
  490. (*                                                                      *)
  491. (*----------------------------------------------------------------------*)
  492.  
  493. VAR
  494.    Old_Lcr   : BYTE;
  495.    Break_Lcr : BYTE;
  496.  
  497. BEGIN (* Async_Send_Break *)
  498.  
  499.    Old_Lcr   := PORT[ Async_Uart_LCR ];
  500.    Break_Lcr := Old_Lcr;
  501.  
  502.    IF Break_Lcr >  127 THEN Break_Lcr := Break_Lcr - 128;
  503.    IF Break_Lcr <=  63 THEN Break_Lcr := Break_Lcr +  64;
  504.  
  505.    PORT[ Async_Uart_LCR ] := Break_Lcr;
  506.  
  507.    DELAY( Async_Break_Length * 10 );
  508.  
  509.    PORT[ Async_Uart_LCR ] := Old_Lcr;
  510.  
  511. END   (* Async_Send_Break *);
  512.  
  513. (*----------------------------------------------------------------------*)
  514. (*     Async_Send_String --- Send string over communications port       *)
  515. (*----------------------------------------------------------------------*)
  516.  
  517. PROCEDURE Async_Send_String( S : AnyStr );
  518.  
  519. (*----------------------------------------------------------------------*)
  520. (*                                                                      *)
  521. (*     Procedure:  Async_Send_String                                    *)
  522. (*                                                                      *)
  523. (*     Purpose:    Sends string out over communications port            *)
  524. (*                                                                      *)
  525. (*     Calling Sequence:                                                *)
  526. (*                                                                      *)
  527. (*        Async_Send_String( S : AnyStr );                              *)
  528. (*                                                                      *)
  529. (*           S --- String to send                                       *)
  530. (*                                                                      *)
  531. (*     Calls:  Async_Send                                               *)
  532. (*                                                                      *)
  533. (*----------------------------------------------------------------------*)
  534.  
  535. VAR
  536.    I : INTEGER;
  537.  
  538. BEGIN  (* Async_Send_String *)
  539.  
  540.   FOR I := 1 TO LENGTH( S ) DO
  541.      Async_Send( S[I] )
  542.  
  543. END    (* Async_Send_String *);
  544.  
  545. (*----------------------------------------------------------------------*)
  546. (*     Async_Send_String_With_Delays --- Send string with timed delays  *)
  547. (*----------------------------------------------------------------------*)
  548.  
  549. PROCEDURE Async_Send_String_With_Delays( S          : AnyStr;
  550.                                          Char_Delay : INTEGER;
  551.                                          EOS_Delay  : INTEGER  );
  552.  
  553. (*----------------------------------------------------------------------*)
  554. (*                                                                      *)
  555. (*     Procedure:  Async_Send_String_With_Delays                        *)
  556. (*                                                                      *)
  557. (*     Purpose:    Sends string out over communications port with       *)
  558. (*                 specified delays for each character and at the       *)
  559. (*                 end of the string.                                   *)
  560. (*                                                                      *)
  561. (*     Calling Sequence:                                                *)
  562. (*                                                                      *)
  563. (*        Async_Send_String_With_Delays( S          : AnyStr ;          *)
  564. (*                                       Char_Delay : INTEGER;          *)
  565. (*                                       EOS_Delay  : INTEGER );        *)
  566. (*                                                                      *)
  567. (*           S          --- String to send                              *)
  568. (*           Char_Delay --- Number of milliseconds to delay after       *)
  569. (*                          sending each character                      *)
  570. (*           EOS_Delay  --- Number of milleseconds to delay after       *)
  571. (*                          sending last character in string            *)
  572. (*                                                                      *)
  573. (*     Calls:  Async_Send                                               *)
  574. (*             Async_Send_String                                        *)
  575. (*             Length                                                   *)
  576. (*             Delay                                                    *)
  577. (*                                                                      *)
  578. (*     Remarks:                                                         *)
  579. (*                                                                      *)
  580. (*        This routine is useful when writing routines to perform       *)
  581. (*        non-protocol uploads.  Many computer systems require delays   *)
  582. (*        between receipt of characters for correct processing.  The    *)
  583. (*        delay for end-of-string usually applies when the string       *)
  584. (*        represents an entire line of a file.                          *)
  585. (*                                                                      *)
  586. (*        If delays are not required, Async_Send_String is faster.      *)
  587. (*        This routine will call Async_Send_String if no character      *)
  588. (*        delay is to be done.                                          *)
  589. (*                                                                      *)
  590. (*----------------------------------------------------------------------*)
  591.  
  592. VAR
  593.    I : INTEGER;
  594.  
  595. BEGIN  (* Async_Send_String_With_Delays *)
  596.  
  597.    IF Char_Delay <= 0 THEN
  598.       Async_Send_String( S )
  599.    ELSE
  600.       FOR I := 1 TO LENGTH( S ) DO
  601.          BEGIN
  602.             Async_Send( S[I] );
  603.             DELAY( Char_Delay );
  604.          END;
  605.  
  606.    IF ( EOS_Delay > 0 ) THEN
  607.       DELAY( EOS_Delay );
  608.  
  609. END    (* Async_Send_String_With_Delays *);
  610.  
  611. (*----------------------------------------------------------------------*)
  612. (*      Async_Percentage_Used --- Report Percentage Buffer Filled       *)
  613. (*----------------------------------------------------------------------*)
  614.  
  615. FUNCTION Async_Percentage_Used : REAL;
  616.  
  617. (*----------------------------------------------------------------------*)
  618. (*                                                                      *)
  619. (*     Function:   Async_Percent_Used                                   *)
  620. (*                                                                      *)
  621. (*     Purpose:    Reports percentage of com buffer currently filled    *)
  622. (*                                                                      *)
  623. (*     Calling Sequence:                                                *)
  624. (*                                                                      *)
  625. (*        Percentage := Async_Percentage_Used : Real;                   *)
  626. (*                                                                      *)
  627. (*           Percentage gets how much of buffer is filled;              *)
  628. (*           value goes from 0.0 (empty) to 1.0 (totally full).         *)
  629. (*                                                                      *)
  630. (*     Calls:  None                                                     *)
  631. (*                                                                      *)
  632. (*     Remarks:                                                         *)
  633. (*                                                                      *)
  634. (*       This routine is helpful when incorporating handshaking into    *)
  635. (*       a communications program.  For example, assume that the host   *)
  636. (*       computer uses the XON/XOFF (DC1/DC3) protocol.  Then the       *)
  637. (*       PC program should issue an XOFF  to the host when the value    *)
  638. (*       returned by Async_Percentage_Used > .75 or so.  When the       *)
  639. (*       utilization percentage drops below .25 or so, the PC program   *)
  640. (*       should transmit an XON.                                        *)
  641. (*                                                                      *)
  642. (*----------------------------------------------------------------------*)
  643.  
  644. BEGIN (* Async_Percentage_Used *)
  645.  
  646.    Async_Percentage_Used := Async_Buffer_Used / ( Async_Buffer_Size + 1 );
  647.  
  648. END   (* Async_Percentage_Used *);
  649.  
  650. (*----------------------------------------------------------------------*)
  651. (*     Async_Purge_Buffer --- Purge communications input buffer         *)
  652. (*----------------------------------------------------------------------*)
  653.  
  654. PROCEDURE Async_Purge_Buffer;
  655.  
  656. (*----------------------------------------------------------------------*)
  657. (*                                                                      *)
  658. (*     Procedure:  Async_Purge_Buffer                                   *)
  659. (*                                                                      *)
  660. (*     Purpose:    Purges communications input buffer                   *)
  661. (*                                                                      *)
  662. (*     Calling Sequence:                                                *)
  663. (*                                                                      *)
  664. (*        Async_Purge_Buffer;                                           *)
  665. (*                                                                      *)
  666. (*     Calls:  Async_Receive                                            *)
  667. (*                                                                      *)
  668. (*----------------------------------------------------------------------*)
  669.  
  670. VAR
  671.    C: CHAR;
  672.    L: INTEGER;
  673.  
  674. BEGIN  (* Async_Purge_Buffer *)
  675.  
  676.    L     := 10000 DIV Async_Baud_Rate;
  677.  
  678.    IF L <= 0 THEN
  679.       L := 3;
  680.  
  681.    REPEAT
  682.       DELAY( L )
  683.    UNTIL ( NOT Async_Receive( C ) );
  684.  
  685. END    (* Async_Purge_Buffer *);
  686.  
  687. (*----------------------------------------------------------------------*)
  688. (*          Async_Peek --- Peek ahead in communications buffer          *)
  689. (*----------------------------------------------------------------------*)
  690.  
  691. FUNCTION Async_Peek( Nchars : INTEGER ) : CHAR;
  692.  
  693. (*----------------------------------------------------------------------*)
  694. (*                                                                      *)
  695. (*     Function:   Async_Peek                                           *)
  696. (*                                                                      *)
  697. (*     Purpose:    Peeks ahead in comm buffer                           *)
  698. (*                                                                      *)
  699. (*     Calling Sequence:                                                *)
  700. (*                                                                      *)
  701. (*        Ch := Async_Peek( NChars: INTEGER) : CHAR;                    *)
  702. (*                                                                      *)
  703. (*           NChars --- # of characters to peek ahead                   *)
  704. (*           Ch     --- returned (peeked) character                     *)
  705. (*                                                                      *)
  706. (*     Calls:  None                                                     *)
  707. (*                                                                      *)
  708. (*----------------------------------------------------------------------*)
  709.  
  710. VAR
  711.    I: INTEGER;
  712.    H: INTEGER;
  713.    T: INTEGER;
  714.  
  715. BEGIN (* Async_Peek *)
  716.  
  717.    H := Async_Buffer_Head;
  718.    T := Async_Buffer_Tail;
  719.  
  720.    I := ( T + NChars ) MOD Async_Buffer_Size;
  721.  
  722.    IF ( H < T ) THEN
  723.       IF ( ( I > H ) AND ( I < T ) ) THEN
  724.          Async_Peek := CHR( 0 )
  725.       ELSE
  726.          Async_Peek := Async_Buffer_Ptr^[ I ]
  727.    ELSE
  728.       IF ( ( I > H ) OR ( I < T ) ) THEN
  729.             Async_Peek := CHR( 0 )
  730.          ELSE
  731.             Async_Peek := Async_Buffer_Ptr^[ I ];
  732.  
  733. END   (* Async_Peek *);
  734.  
  735. (*----------------------------------------------------------------------*)
  736. (*         Async_Setup_Port --- Setup port address and IRQ line         *)
  737. (*----------------------------------------------------------------------*)
  738.  
  739. PROCEDURE Async_Setup_Port( ComPort       : INTEGER;
  740.                             Base_Address  : INTEGER;
  741.                             IRQ_Line      : INTEGER;
  742.                             Int_Numb      : INTEGER );
  743.  
  744. (*----------------------------------------------------------------------*)
  745. (*                                                                      *)
  746. (*     Procedure:  Async_Setup_Port                                     *)
  747. (*                                                                      *)
  748. (*     Purpose:    Sets up port address and IRQ line                    *)
  749. (*                                                                      *)
  750. (*     Calling Sequence:                                                *)
  751. (*                                                                      *)
  752. (*        Async_Setup_Port( ComPort       : INTEGER;                    *)
  753. (*                          Base_Address  : INTEGER;                    *)
  754. (*                          IRQ_Line      : INTEGER;                    *)
  755. (*                          Int_Numb      : INTEGER );                  *)
  756. (*                                                                      *)
  757. (*           ComPort      --- which port (1 though MaxComPorts)         *)
  758. (*           Base_Address --- Base address of port.  If -1, then        *)
  759. (*                            standard default address used.            *)
  760. (*           IRQ_Line     --- IRQ line for interrupts for port.  If -1, *)
  761. (*                            then standard default irq line used.      *)
  762. (*           Int_Numb     --- Interrupt vector number for port.  If -1, *)
  763. (*                            then standard default interrupt # used.   *)
  764. (*                                                                      *)
  765. (*     Calls:  None                                                     *)
  766. (*                                                                      *)
  767. (*----------------------------------------------------------------------*)
  768.  
  769. VAR
  770.    Port_Offset : INTEGER;
  771.  
  772. BEGIN  (* Async_Setup_Port *)
  773.  
  774.    IF ( ( ComPort > 0 ) AND ( ComPort <= MaxComPorts ) ) THEN
  775.       BEGIN
  776.          IF ( Base_Address = -1 ) THEN
  777.             Base_Address := Default_Com_Base[ComPort];
  778.          IF ( IRQ_Line = -1 ) THEN
  779.             IRQ_Line := Default_Com_IRQ[ComPort];
  780.          IF ( Int_Numb = -1 ) THEN
  781.             Int_Numb := Default_Com_Int[ComPort];
  782.          Com_Base [ComPort]   := Base_Address;
  783.          Com_Irq  [ComPort]   := IRQ_Line;
  784.          Com_Int  [ComPort]   := Int_Numb;
  785.          Port_Offset          := RS232_Base + ( PRED( ComPort ) SHL 1 );
  786.          MemW[$0:Port_Offset] := Base_Address;
  787.       END;
  788.  
  789. END    (* Async_Setup_Port *);
  790.  
  791. (*----------------------------------------------------------------------*)
  792. (*         Async_Release_Buffers --- Release buffers for serial ports   *)
  793. (*----------------------------------------------------------------------*)
  794.  
  795. PROCEDURE Async_Release_Buffers;
  796.  
  797. (*----------------------------------------------------------------------*)
  798. (*                                                                      *)
  799. (*     Procedure:  Async_Release_Buffers;                               *)
  800. (*                                                                      *)
  801. (*     Purpose:    Releases send and receive buffers                    *)
  802. (*                                                                      *)
  803. (*     Calling Sequence:                                                *)
  804. (*                                                                      *)
  805. (*        Async_Release_Buffers;                                        *)
  806. (*                                                                      *)
  807. (*     Calls:  None                                                     *)
  808. (*                                                                      *)
  809. (*----------------------------------------------------------------------*)
  810.  
  811. BEGIN  (* Async_Release_Buffers *)
  812.  
  813.                              (* If port open, close it down first.  *)
  814.    IF Async_Open_Flag THEN
  815.       Async_Close( FALSE );
  816.  
  817.    FREEMEM( Async_Buffer_Ptr  , Async_Buffer_Size  + 1 );
  818.    FREEMEM( Async_OBuffer_Ptr , Async_OBuffer_Size + 1 );
  819.    SetIntVec($03, @Set_Reboot_Vector);
  820.  
  821. END    (* Async_Release_Buffers *);
  822.  
  823. (*----------------------------------------------------------------------*)
  824. (*   Async_Flush_Input_Buffer --- Flush input buffer for serial port    *)
  825. (*----------------------------------------------------------------------*)
  826.  
  827. PROCEDURE Async_Flush_Input_Buffer;
  828.  
  829. (*----------------------------------------------------------------------*)
  830. (*                                                                      *)
  831. (*     Procedure:  Async_Flush_Input_Buffer;                            *)
  832. (*                                                                      *)
  833. (*     Purpose:    Flushes input buffer for serial port.                *)
  834. (*                                                                      *)
  835. (*     Calling Sequence:                                                *)
  836. (*                                                                      *)
  837. (*        Async_Flush_Input_Buffer;                                     *)
  838. (*                                                                      *)
  839. (*     Calls:  None                                                     *)
  840. (*                                                                      *)
  841. (*----------------------------------------------------------------------*)
  842.  
  843. BEGIN  (* Async_Flush_Output_Buffer *)
  844.  
  845.    Async_Buffer_Head  := Async_Buffer_Tail;
  846.    Async_Buffer_Used  := 0;
  847.  
  848. END    (* Async_Flush_Input_Buffer *);
  849.  
  850. (*----------------------------------------------------------------------*)
  851. (*   Async_Drain_Input_Buffer --- Wait for input buffer to drain        *)
  852. (*----------------------------------------------------------------------*)
  853.  
  854. PROCEDURE Async_Drain_Input_Buffer( Max_Wait_Time : INTEGER );
  855.  
  856. (*----------------------------------------------------------------------*)
  857. (*                                                                      *)
  858. (*     Procedure:  Async_Drain_Input_Buffer;                            *)
  859. (*                                                                      *)
  860. (*     Purpose:    Waits for input buffer to drain.                     *)
  861. (*                                                                      *)
  862. (*     Calling Sequence:                                                *)
  863. (*                                                                      *)
  864. (*        Async_Drain_Input_Buffer( Max_Wait_Time : INTEGER );          *)
  865. (*                                                                      *)
  866. (*           Max_Wait_Time --- Maximum # of seconds to wait for         *)
  867. (*                             input buffer to drain.                   *)
  868. (*                                                                      *)
  869. (*     Calls:  TimeOfDay                                                *)
  870. (*             TimeDiff                                                 *)
  871. (*             GiveUpTime                                               *)
  872. (*                                                                      *)
  873. (*----------------------------------------------------------------------*)
  874.  
  875. VAR
  876.    T1 : LONGINT;
  877.  
  878. BEGIN  (* Async_Drain_Input_Buffer *)
  879.  
  880.    T1 := TimeOfDay;
  881.  
  882.    WHILE( ( Async_Buffer_Head <> Async_Buffer_Tail    ) AND
  883.           ( TimeDiff( T1 , TimeOfDay ) <= Max_Wait_Time )     ) DO
  884. {$IFDEF MTASK}
  885.       GiveUpTime( 1 );
  886. {$ELSE}
  887.       ;
  888. {$ENDIF}
  889.  
  890. END    (* Async_Drain_Input_Buffer *);
  891.  
  892. (*----------------------------------------------------------------------*)
  893. (*   Async_Flush_Output_Buffer --- Flush output buffer for serial port  *)
  894. (*----------------------------------------------------------------------*)
  895.  
  896. PROCEDURE Async_Flush_Output_Buffer;
  897.  
  898. (*----------------------------------------------------------------------*)
  899. (*                                                                      *)
  900. (*     Procedure:  Async_Flush_Output_Buffer;                           *)
  901. (*                                                                      *)
  902. (*     Purpose:    Flushes output buffer for serial port.               *)
  903. (*                                                                      *)
  904. (*     Calling Sequence:                                                *)
  905. (*                                                                      *)
  906. (*        Async_Flush_Output_Buffer;                                    *)
  907. (*                                                                      *)
  908. (*     Calls:  None                                                     *)
  909. (*                                                                      *)
  910. (*----------------------------------------------------------------------*)
  911.  
  912. BEGIN  (* Async_Flush_Output_Buffer *)
  913.  
  914.    Async_OBuffer_Head  := Async_OBuffer_Tail;
  915.    Async_OBuffer_Used  := 0;
  916.  
  917. END    (* Async_Flush_Output_Buffer *);
  918.  
  919. (*----------------------------------------------------------------------*)
  920. (*   Async_Drain_Output_Buffer --- Wait for output buffer to drain      *)
  921. (*----------------------------------------------------------------------*)
  922.  
  923. PROCEDURE Async_Drain_Output_Buffer( Max_Wait_Time : INTEGER );
  924.  
  925. (*----------------------------------------------------------------------*)
  926. (*                                                                      *)
  927. (*     Procedure:  Async_Drain_Output_Buffer;                           *)
  928. (*                                                                      *)
  929. (*     Purpose:    Waits for output buffer to drain.                    *)
  930. (*                                                                      *)
  931. (*     Calling Sequence:                                                *)
  932. (*                                                                      *)
  933. (*        Async_Drain_Output_Buffer( Max_Wait_Time : INTEGER );         *)
  934. (*                                                                      *)
  935. (*           Max_Wait_Time --- Maximum # of seconds to wait for         *)
  936. (*                             output buffer to drain.                  *)
  937. (*                                                                      *)
  938. (*     Calls:  TimeOfDay                                                *)
  939. (*             TimeDiff                                                 *)
  940. (*             GiveUpTime                                               *)
  941. (*                                                                      *)
  942. (*----------------------------------------------------------------------*)
  943.  
  944. VAR
  945.    T1 : LONGINT;
  946.  
  947. BEGIN  (* Async_Drain_Output_Buffer *)
  948.  
  949.    T1 := TimeOfDay;
  950.  
  951.    WHILE( ( Async_OBuffer_Head <> Async_OBuffer_Tail    ) AND
  952.           ( TimeDiff( T1 , TimeOfDay ) <= Max_Wait_Time )     ) DO
  953. {$IFDEF MTASK}
  954.       GiveUpTime( 1 );
  955. {$ELSE}
  956.       ;
  957. {$ENDIF}
  958.  
  959. END    (* Async_Drain_Output_Buffer *);
  960.  
  961. (*----------------------------------------------------------------------*)
  962. (*   Async_Port_Address_Given --- Check if port address in memory       *)
  963. (*----------------------------------------------------------------------*)
  964.  
  965. FUNCTION Async_Port_Address_Given( Com_Port : INTEGER ) : BOOLEAN;
  966.  
  967. (*----------------------------------------------------------------------*)
  968. (*                                                                      *)
  969. (*     Procedure:  Async_Port_Address_Given;                            *)
  970. (*                                                                      *)
  971. (*     Purpose:    Checks if port address in memory.                    *)
  972. (*                                                                      *)
  973. (*     Calling Sequence:                                                *)
  974. (*                                                                      *)
  975. (*        There := Async_Port_Address_Given( Com_Port : INTEGER ) :     *)
  976. (*                                         BOOLEAN;                     *)
  977. (*                                                                      *)
  978. (*           Com_Port --- Port to check (1 through MaxComPorts)         *)
  979. (*           There    --- TRUE if port address in memory.               *)
  980. (*                                                                      *)
  981. (*----------------------------------------------------------------------*)
  982.  
  983. VAR
  984.    Port_Offset : INTEGER;
  985.  
  986. BEGIN  (* Async_Port_Address_Given *)
  987.  
  988.    IF ( ( Com_Port > 0 ) AND ( Com_Port < MaxComPorts ) ) THEN
  989.       BEGIN
  990.          Port_Offset              := RS232_Base + ( PRED( Com_Port ) SHL 1 );
  991.          Async_Port_Address_Given := ( MemW[$0:Port_Offset] <> 0 );
  992.       END
  993.    ELSE
  994.       Async_Port_Address_Given := FALSE;
  995.  
  996. END    (* Async_Port_Address_Given *);
  997.  
  998. (*----------------------------------------------------------------------*)
  999. (*     Async_Set_Rejection --- Set bad character rejection handling     *)
  1000. (*----------------------------------------------------------------------*)
  1001.  
  1002. PROCEDURE Async_Set_Rejection( Reject_Bad : BOOLEAN; Reject_Char : CHAR );
  1003.  
  1004. (*----------------------------------------------------------------------*)
  1005. (*                                                                      *)
  1006. (*     Procedure:  Async_Set_Rejection;                                 *)
  1007. (*                                                                      *)
  1008. (*     Purpose:    Sets bad character rejection handling.               *)
  1009. (*                                                                      *)
  1010. (*     Calling Sequence:                                                *)
  1011. (*                                                                      *)
  1012. (*        Async_Set_Rejection( Reject_Bad:BOOLEAN; Reject_Char:CHAR );  *)
  1013. (*                                                                      *)
  1014. (*           Reject_Bad   --- TRUE to activate rejection of bad         *)
  1015. (*                            characters, FALSE to deactivate.          *)
  1016. (*           Reject_Char  --- Character to replace bad character with.  *)
  1017. (*                                                                      *)
  1018. (*----------------------------------------------------------------------*)
  1019.  
  1020. BEGIN  (* Async_Set_Rejection *)
  1021.  
  1022.    Async_Noise_Char   := Reject_Char;
  1023.    Async_Reject_Noise := Reject_Bad;
  1024.  
  1025. END    (* Async_Set_Rejection *);
  1026.